﻿using System;
using System.Windows.Input;

namespace vBridge.Design.Mvvm.Command
{
    public class RelayCommand<T> : ICommand
    {
        private readonly Action<T> _action;
        private readonly Predicate<T> _predicate;

        public RelayCommand(Action<T> action)
            : this(action, o => true)
        {
        }

        public RelayCommand(Action<T> action, Predicate<T> predicate)
        {
            _action = action;
            _predicate = predicate;
        }

        public event EventHandler CanExecuteChanged;

        public virtual Boolean CanExecute(Object parameter)
        {
            // No parameter:
            if (parameter == null)
                return _predicate(default(T));

            // With parameter:
            if (parameter is T)
                return _predicate((T) parameter);
            throw new InvalidCastException(String.Format("Cannot cast a '{0}' to a '{1}'.", parameter.GetType(),
                typeof (T)));
        }

        public virtual void Execute(Object parameter)
        {
            // No parameter:
            if (parameter == null)
            {
                _action(default(T));
                return;
            }

            // With parameter:
            if (!(parameter is T))
                throw new InvalidCastException(String.Format("Cannot cast a '{0}' to a '{1}'.", parameter.GetType(),
                    typeof (T)));
            _action((T) parameter);
        }
    }
}